package controller

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"encoding/json"
	"net/http"
	"net/url"
	"server_cluster/common/logger"
	"server_cluster/common/tools"
	"sort"
	"strconv"
	"time"

	"server_cluster/http/http_config"
	"server_cluster/http/model"
	"server_cluster/http/pkg/endec"
	"server_cluster/http/pkg/httpclient"

	"github.com/gin-gonic/gin"
)

var reqHostList = []string{
	"http://pnew.biligame.net",
	"http://line3-qcloud-game-api-adapter-na.biligame.net",
	"http://line3-game-api-adapter-na-sh.biligame.net",
}

// tap第三方sdk登录
func (c *Controller) accountSdkLogin(ctx *gin.Context) {
	req := new(model.AccountSdkLoginReq)
	err := ctx.ShouldBindJSON(req)
	if err != nil {
		logger.Error("parse json error: %v", err)
		ctx.JSON(http.StatusOK, ParamError)
		return
	}
	if c.s.ServerStartTime >= 0 && tools.TimeNow() < c.s.ServerStartTime {
		ctx.JSON(http.StatusOK, NotServerStartTime)
		return
	}

	//if http_config.GetConfig().RegisterMax >= c.s.PlayerCount {
	//	ctx.JSON(http.StatusOK, RegisterOverLimit)
	//	return
	//}

	rspRegionList := make([]*model.Region, 0)
	if http_config.CONF.DevEnv {
		rspRegionList = []*model.Region{
			{
				Title: "root服",
				Addr:  "192.168.3.247:9188",
			},
			{
				Title: "内网1服(杜勇)",
				Addr:  "192.168.3.247:11888",
			},
			{
				Title: "内网2服(张艺华)",
				Addr:  "192.168.3.247:21888",
			},
			{
				Title: "内网3服(史玉鑫)",
				Addr:  "192.168.3.247:31888",
			},
			{
				Title: "内网4服(王怡冰)",
				Addr:  "192.168.3.247:41888",
			},
			{
				Title: "内网5服(大帅)",
				Addr:  "192.168.3.247:51888",
			},
			{
				Title: "内网6服(谭秉林)",
				Addr:  "192.168.3.247:6188",
			},
		}
	} else {
		if !http_config.GetConfig().DevEnv {
			if len(c.s.ServerList) == 0 {
				ctx.JSON(http.StatusOK, StopServerError)
				return
			}
		}
		sort.Slice(c.s.ServerList, func(i, j int) bool {
			return c.s.ServerList[i].Stock > c.s.ServerList[j].Stock
		})
		rspRegionList = append(rspRegionList, c.s.ServerList[0])
	}
	userName := ""
	nickname := ""
	headImageUrl := ""
	passWord := ""
	switch req.Platform {
	case model.PlatformInternal:
		internalLogin := new(model.InternalLogin)
		err := json.Unmarshal([]byte(req.JsonData), internalLogin)
		if err != nil {
			logger.Error("parse json error: %v", err)
			ctx.JSON(http.StatusOK, ParamError)
			return
		}
		if internalLogin.UserName == "" {
			ctx.JSON(http.StatusOK, "userName is empty")
			return
		}
		userName = internalLogin.UserName
		nickname = internalLogin.UserName
		passWord = internalLogin.Token
		if (len(userName) < 6 || len(userName) > 30) || (len(passWord) < 6 || len(passWord) > 30) {
			ctx.JSON(http.StatusOK, GmAccountPasswordLength)
			return
		}
		if tools.CheckString(userName) {
			ctx.JSON(http.StatusOK, GmUsernameFormatError)
			return
		}
		if tools.CheckString(passWord) {
			ctx.JSON(http.StatusOK, GmPasswordFormatError)
			return
		}
	case model.PlatformTap:
		tapLogin := new(model.TapLogin)
		err := json.Unmarshal([]byte(req.JsonData), tapLogin)
		if err != nil {
			logger.Error("parse json error: %v", err)
			ctx.JSON(http.StatusOK, ParamError)
			return
		}
		if !http_config.GetConfig().TapSdkSkip {
			// tap mac token计算
			nonce := "8IBTHwOdqNKAWeKl7plt66=="
			timestamp := strconv.FormatInt(time.Now().Unix(), 10)
			reqHost := "open.tapapis.cn"
			reqURI := "/account/profile/v1?client_id=" + http_config.GetConfig().TapSdkClientId
			reqURL := "https://" + reqHost + reqURI
			macStr := timestamp + "\n" + nonce + "\n" + "GET" + "\n" + reqURI + "\n" + reqHost + "\n" + "443" + "\n\n"
			key := []byte(tapLogin.MacKey)
			mac := hmac.New(sha1.New, key)
			mac.Write([]byte(macStr))
			macBase64 := base64.StdEncoding.EncodeToString(mac.Sum(nil))
			authorization := "MAC id=" + "\"" + tapLogin.AccessToken + "\"" + "," + "ts=" + "\"" + timestamp + "\"" + "," + "nonce=" + "\"" + nonce + "\"" + "," + "mac=" + "\"" + macBase64 + "\""
			tapAccountRsp, err := httpclient.GetJson[model.TapAccountRsp](reqURL, authorization)
			if err != nil {
				logger.Error("tap sdk login http get error: %v, req: %v", err, req)
				ctx.JSON(http.StatusOK, UnknownError)
				return
			}
			if tapAccountRsp.Data.Code != 0 {
				logger.Error("tap sdk login error, req: %v, rsp: %v", req, tapAccountRsp)
				ctx.JSON(http.StatusOK, AccountLoginError)
				return
			}
			userName = tapAccountRsp.Data.OpenId
			nickname = tapAccountRsp.Data.Name
			headImageUrl = tapAccountRsp.Data.Avatar
		} else {
			userName = endec.Sha1Str(tapLogin.AccessToken)
		}
	case model.PlatformBiliBili:
		biliLogin := new(model.BiliLogin)
		err := json.Unmarshal([]byte(req.JsonData), biliLogin)
		if err != nil {
			logger.Error("parse json error: %v", err)
			ctx.JSON(http.StatusOK, ParamError)
			return
		}

		var postData = url.Values{}
		postData.Add("game_id", strconv.Itoa(int(http_config.GetConfig().BiliGameId)))
		postData.Add("merchant_id", strconv.Itoa(int(http_config.GetConfig().BiliMerchantId)))
		postData.Add("uid", biliLogin.Uid)
		postData.Add("version", "1")
		postData.Add("timestamp", strconv.Itoa(int(time.Now().UnixNano())))
		postData.Add("access_key", biliLogin.AccessToken)
		postData.Add("sign", tools.QueryMd5(&postData))

		reqURI := "/api/server/session.verify"
		biliAccountRsp := &model.BiliAccountRsp{}
		for _, v := range reqHostList {
			reqURL := v + reqURI
			biliAccountRsp, err = httpclient.PostJson4BiliBili[model.BiliAccountRsp](reqURL, postData.Encode())
			if err == nil {
				break
			}
		}
		if biliAccountRsp.Code != 0 {
			logger.Error("bili sdk login error, req: %v, rsp: %v", req, biliAccountRsp)
			ctx.JSON(http.StatusOK, biliAccountRsp)
			return
		}
		userName = biliAccountRsp.OpenId
		nickname = biliAccountRsp.Uname
	case model.Platform4399:
		login4399 := new(model.Login4399)
		err = json.Unmarshal([]byte(req.JsonData), login4399)
		if err != nil {
			logger.Error("parse json error: %v", err)
			ctx.JSON(http.StatusOK, ParamError)
			return
		}
		reqURL := "http://m.4399api.com/openapi/oauth-check.html?" + "state=" + login4399.State + "&uid=" + login4399.Uid +
			"&key=" + http_config.GetConfig().Key4399
		accountRsp4399, err := httpclient.GetJson[model.AccountRsp4399](reqURL)
		if err != nil {
			logger.Error("4399 sdk login http get error: %v, req: %v", err, req)
			ctx.JSON(http.StatusOK, UnknownError)
			return
		}
		code, err := strconv.Atoi(accountRsp4399.Code)
		if err != nil {
			ctx.JSON(http.StatusOK, accountRsp4399)
		}
		if code != 100 {
			logger.Error("4399 sdk login error, req: %v, rsp: %v", req, accountRsp4399)
			ctx.JSON(http.StatusOK, accountRsp4399)
			return
		}
		userName = accountRsp4399.Result.Uid
		nickname = login4399.NickName

	case model.PlatformHaoYouKuaiBao:
		loginHYKB := new(model.LoginHYKB)
		err = json.Unmarshal([]byte(req.JsonData), loginHYKB)
		if err != nil {
			logger.Error("parse json error: %v", err)
			ctx.JSON(http.StatusOK, ParamError)
			return
		}
		reqURL := "https://api.3839app.com/kuaibao/android/devsdk.php"
		var data = url.Values{}
		data.Add("c", "authgame")
		data.Add("a", "checkAccessToken")
		data.Add("v", "1546")
		data.Add("app_id", http_config.GetConfig().KeyHYKB)
		data.Add("uid", strconv.Itoa(loginHYKB.Uid))
		data.Add("access_token", loginHYKB.AccessToken)
		accountRspHYKB, err := httpclient.PostJson4FormData[model.AccountRspHYKB](reqURL, &data)
		if err != nil {
			logger.Error("4399 sdk login http get error: %v, req: %v", err, req)
			ctx.JSON(http.StatusOK, UnknownError)
			return
		}
		if accountRspHYKB.Code != 100 {
			logger.Error("4399 sdk login error, req: %v, rsp: %v", req, accountRspHYKB)
			ctx.JSON(http.StatusOK, accountRspHYKB)
			return
		}
		userName = strconv.Itoa(loginHYKB.Uid)
		nickname = loginHYKB.NickName
	}

	var uid int64
	var token string
	uid, token, err = c.s.AccountLogin(nickname, headImageUrl, userName, passWord, ctx.ClientIP(), req.Platform)
	if err != nil {
		logger.Error("account login error: %v", err)
		ctx.JSON(http.StatusOK, AccountLoginError)
		return
	}
	ctx.JSON(http.StatusOK, &model.CommonRsp{Code: 0, Data: &model.AccountSdkLoginRsp{PassWord: passWord, UserName: userName, Uid: int32(uid), Token: token, RegionList: rspRegionList}})
}
